/**
 *
 */
package com.rf.richfitwheel.workflow.service.impl;

import com.rf.richfitwheel.admin.feignclient.FSysUserService;
import com.rf.richfitwheel.admin.sys.dao.SqlAdapterMapper;
import com.rf.richfitwheel.admin.sys.model.OrgVO;
import com.rf.richfitwheel.admin.sys.vo.UserVO;
import com.rf.richfitwheel.admin.utils.UserUtil;
import com.rf.richfitwheel.common.exception.BusinessException;
import com.rf.richfitwheel.common.utils.DateUtils;
import com.rf.richfitwheel.common.utils.PageUtils;
import com.rf.richfitwheel.workflow.conf.WorkflowContants;
import com.rf.richfitwheel.workflow.dao.WfCommonMapper;
import com.rf.richfitwheel.workflow.dao.WfProcessTaskMapper;
import com.rf.richfitwheel.workflow.dao.WfStationProcessMapper;
import com.rf.richfitwheel.workflow.dao.WfStationProcessOrderMapper;
import com.rf.richfitwheel.workflow.entity.WfTaskParam;
import com.rf.richfitwheel.workflow.entity.WfTaskVo;
import com.rf.richfitwheel.workflow.feignclient.SysOrgFeignService;
import com.rf.richfitwheel.workflow.model.*;
import com.rf.richfitwheel.workflow.service.*;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.*;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.runtime.ProcessInstanceBuilderImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceBuilder;
import org.activiti.engine.task.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hushouquan
 *
 */
@Service
public class WfTaskServiceImpl implements WfTaskService {

    @Autowired
    private WfProcessService wfProcessService;
    @Autowired
    private WfProcessTransferService wfProcessTransferService;
    @Autowired
    private ModelService modelService;

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    protected WfProcessTaskService wfProcessTaskService;
    @Autowired
    private FSysUserService fSysUserService;
    @Autowired
    private PortalTodoSync portalTodoSync;
    
    @Autowired
    private WfProcessTaskMapper wfProcessTaskMapper;
    
    @Autowired
    private WfStationProcessOrderMapper wfStationProcessOrderMapper;
    
    @Autowired
    private WfStationProcessMapper wfStationProcessMapper;
    @Autowired
    private SysOrgFeignService sysOrgFeignService;

    @Autowired
    private WfCommonMapper wfCommonMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WfTaskParam submitTask(WfTaskParam params, UserVO user) throws Exception {
        Map<String, Object> startVariables = new HashMap<>(params.getVariables());//流程启动参数
        params.getVariables().remove("startUserId");
        params.getVariables().remove("startUserName");
        Map<String, Object> variables = new HashMap<>(params.getVariables());//任务参数
        /*if (StringUtils.isNotBlank(params.getApproveUserId())) {
            variables.put("approveUserId", params.getApproveUserId());//审批人id加入任务参数中去
        } else {
            variables.remove("approveUserId");
            if (StringUtils.isNotBlank(params.getProcessInstanceId())) {
                runtimeService.removeVariable(params.getProcessInstanceId(), "approveUserId");
            }
        }*/
        if (StringUtils.isBlank(params.getTaskId())) {
            Assert.notNull(params.getSecretLevel(), "必须指定流程密级");
            //新发起流程创建任务
            identityService.setAuthenticatedUserId(user.getId());
            String processKey = null;
            if (StringUtils.isBlank(params.getProcessKey())) {
                processKey = "wf_" + params.getOrgCode().replaceAll("#", ".") + "_" + params.getProcessCode();
            } else {
                processKey = params.getProcessKey();
            }
            startVariables.put("startUserName", user.getStaffName());//发起人姓名用于模糊查询,姓名不是用户名
            startVariables.put("startUserId", user.getId());//发起人id
//            List<ProcessDefinition> def = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processKey).list();
            ProcessDefinition lastDef = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processKey).latestVersion().singleResult();
            if(lastDef == null){
                throw new BusinessException("没有为该业务配置流程，请先配置流程！");
            }
            if (org.apache.commons.lang.StringUtils.isBlank(params.getProcessInsName())){
                throw new BusinessException("请传入流程摘要：WfTaskParam.processInsName");
            }
            //获取首节点岗位下用户，如果用户中不包含当前用户则认为用户没权限，不让提交流程
            UserTask userTask = getFirstUserTaskDef(lastDef.getId());
            List<String> groups = userTask.getCandidateGroups();
            List<com.rf.richfitwheel.admin.sys.model.User> users = fSysUserService.getUserListByStationIds(String.join(",", groups));
            if(users.stream().noneMatch(m -> m.getId().equals(user.getId()))){
                throw new BusinessException("没有该流程权限，不能发起流程！");
            }
            ProcessInstanceBuilderImpl builder = new ProcessInstanceBuilderImpl((RuntimeServiceImpl) runtimeService);
            builder.processDefinitionId(lastDef.getId())
                    .processDefinitionKey(processKey)
                    .businessKey(params.getBusinessKey())
                    .processInstanceName(params.getProcessInsName())
                    .secretLevel(params.getSecretLevel())
                    .variables(startVariables);
            ProcessInstance processInstance = builder.start();
//            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey, params.getBusinessKey(), startVariables);
            if(processInstance == null || processInstance.getId() == null)
                throw new BusinessException("没有为该业务配置流程，请先配置流程！");
            String processInstanceId = processInstance.getId();
            /*//流程摘要
            if (org.apache.commons.lang.StringUtils.isNotBlank(params.getProcessInsName())) {
                runtimeService.setProcessInstanceName(processInstanceId, params.getProcessInsName());
            }
            //密级
            if (params.getSecretLevel() == null) {
                throw new BusinessException("需要传入数据密级！");
            }else{
                runtimeService.setProcessInstanceSecretLevel(processInstanceId, params.getSecretLevel());
            }*/
            params.setProcessInstanceId(processInstanceId);
            processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            this.identityService.setAuthenticatedUserId(null);
            List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            /*for (Task task : tasks) {
                //先发送首节点待办给门户
                portalTodoSync.todoSyncFirst(processInstance, task, params.getModuleType(), user.getId());
            }*/
            if (params.isSkipFirstTask()) {//是否跳过第一个节点
                for (Task task : tasks) {
                    params.setTaskId(task.getId());
                    task.setDescription(WorkflowContants.ProcessResult.START.getValue());//审批结果 发起
                    task.setFileId(params.getFileId());
                    taskService.saveTask(task);
                    taskService.addComment(task.getId(), task.getProcessInstanceId(), StringUtils.isNotBlank(params.getApproveMessage()) ? params.getApproveMessage() : "发起流程");
                    taskService.setVariablesLocal(task.getId(), params.getVariablesLocal());
                    this.complete(task, variables, params.getApproveMessage(), true, params.getApproveUserId());
                }
            }
        } else {
            List<Task> tasks = taskService.createTaskQuery().taskId(params.getTaskId()).list();
            if(tasks.isEmpty()){
                throw new BusinessException("流程待办已被他人处理或不存在！");
            }

            for (Task task : tasks) {
                if(!user.getId().equals(task.getAssignee())){
                    // 没签出的情况下，先看当前用户是否在审批列表里
                    List<IdentityLink> listId = taskService.getIdentityLinksForTask(task.getId());
                    List<String> uGroup = listId.stream().filter(f -> f.getType().equals("candidate")).map(IdentityLink::getGroupId).collect(Collectors.toList());
                    List<String> resUser = fSysUserService.getUserListByStationIds(String.join(",", uGroup)).stream().map(com.rf.richfitwheel.admin.sys.model.User::getId).collect(Collectors.toList());
                    if(resUser.contains(UserUtil.getUser().getId())){
                        //先签出
                        wfProcessService.doClaim(task.getId(), UserUtil.getUser().getId());
//                        task.setAssignee(UserUtil.getUser().getId());
                    }else{
                        throw new BusinessException("对不起，您没有此流程操作权限，如果是未签出任务请到业务系统首页待办任务处进行签出后再处理！");
                    }
                }
                task = taskService.createTaskQuery().taskId(task.getId()).singleResult();
                task.setDescription(params.getApproveAdvice());//审批意见
                task.setFileId(params.getFileId());
                taskService.saveTask(task);
                taskService.addComment(task.getId(), task.getProcessInstanceId(), params.getApproveMessage());
                taskService.setVariablesLocal(task.getId(), params.getVariablesLocal());//本地参数
                if (task.getTaskState().equals(WorkflowContants.ProcessResult.BACK.getValue())) {
                    if (params.getSubmitToPrev().equals("y")) {//是否配置跳转到上一个退回的审批结点
                        List<WfProcessTransfer> wfProcessTransfers = wfProcessTransferService.getListByProcInstIdAndToActIdOrderByCreateDateDesc(task.getProcessInstanceId(), task.getTaskDefinitionKey());
                        if (!wfProcessTransfers.isEmpty()) {//找不着就按顺序提交
                            //退回的时候不需要知道审批人，会默认取上一次审批人
                            runtimeService.removeVariable(params.getProcessInstanceId(), "approveUserId");
                            wfProcessService.doForward(task.getId(), wfProcessTransfers.get(0).getTaskId(), params.getApproveMessage());//
                        } else {
                            this.complete(task, variables, params.getApproveMessage(), false, params.getApproveUserId());
                        }
                    } else {//没有配置就按顺序提交
                        this.complete(task, variables, params.getApproveMessage(), false, params.getApproveUserId());
                    }
                } else {//正常提交
                    this.complete(task, variables, params.getApproveMessage(), false, params.getApproveUserId());
                }
            }
        }
        return params;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public WfTaskParam submitTaskForMq(WfTaskParam params, UserVO user) throws Exception {
        Map<String, Object> startVariables = new HashMap<>(params.getVariables());//流程启动参数
        Map<String, Object> variables = new HashMap<>(params.getVariables());//任务参数
        /*if (StringUtils.isNotBlank(params.getApproveUserId())) {
            variables.put("approveUserId", params.getApproveUserId());//审批人id加入任务参数中去
        } else {
            variables.remove("approveUserId");
            if (StringUtils.isNotBlank(params.getProcessInstanceId())) {
                runtimeService.removeVariable(params.getProcessInstanceId(), "approveUserId");
            }
        }*/
        if (StringUtils.isBlank(params.getTaskId())) {
            Assert.notNull(params.getSecretLevel(), "必须指定流程密级");
            //新发起流程创建任务
            identityService.setAuthenticatedUserId(user.getId());
            String processKey = null;
            if (StringUtils.isBlank(params.getProcessKey())) {
                processKey = "wf_" + params.getOrgCode().replaceAll("#", ".") + "_" + params.getProcessCode();
            } else {
                processKey = params.getProcessKey();
            }
            startVariables.put("startUserName", user.getStaffName());//发起人姓名用于模糊查询,姓名不是用户名
//            List<ProcessDefinition> def = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processKey).list();
            ProcessDefinition lastDef = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processKey).latestVersion().singleResult();
            if(lastDef == null){
                throw new BusinessException("没有为该业务配置流程，请先配置流程！");
            }
            if (org.apache.commons.lang.StringUtils.isBlank(params.getProcessInsName())){
                throw new BusinessException("请传入流程摘要：WfTaskParam.processInsName");
            }
            //获取首节点岗位下用户，如果用户中不包含当前用户则认为用户没权限，不让提交流程
            UserTask userTask = getFirstUserTaskDef(lastDef.getId());
            List<String> groups = userTask.getCandidateGroups();
            List<com.rf.richfitwheel.admin.sys.model.User> users = fSysUserService.getUserListByStationIds(String.join(",", groups));
            if(users.stream().noneMatch(m -> m.getId().equals(user.getId()))){
                throw new BusinessException("没有该流程权限，不能发起流程！");
            }
            ProcessInstanceBuilderImpl builder = new ProcessInstanceBuilderImpl((RuntimeServiceImpl) runtimeService);
            builder.processDefinitionId(lastDef.getId())
                    .processDefinitionKey(processKey)
                    .businessKey(params.getBusinessKey())
                    .processInstanceName(params.getProcessInsName())
                    .secretLevel(params.getSecretLevel())
                    .variables(startVariables);
            ProcessInstance processInstance = builder.start();
//            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey, params.getBusinessKey(), startVariables);
            if(processInstance == null || processInstance.getId() == null)
                throw new BusinessException("没有为该业务配置流程，请先配置流程！");
            String processInstanceId = processInstance.getId();
            //流程摘要
            if (org.apache.commons.lang.StringUtils.isNotBlank(params.getProcessInsName())) {
                runtimeService.setProcessInstanceName(processInstanceId, params.getProcessInsName());
            }
            params.setProcessInstanceId(processInstanceId);
            processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            this.identityService.setAuthenticatedUserId(null);
            List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            /*for (Task task : tasks) {
                //先发送首节点待办给门户
                portalTodoSync.todoSyncFirst(processInstance, task, params.getModuleType(), user.getId());
            }*/
            if (params.isSkipFirstTask()) {//是否跳过第一个节点
                for (Task task : tasks) {
                    params.setTaskId(task.getId());
                    task.setDescription(WorkflowContants.ProcessResult.START.getValue());//审批结果 发起
                    task.setFileId(params.getFileId());
                    taskService.saveTask(task);
                    taskService.addComment(task.getId(), task.getProcessInstanceId(), StringUtils.isNotBlank(params.getApproveMessage()) ? params.getApproveMessage() : "发起流程");
                    taskService.setVariablesLocal(task.getId(), params.getVariablesLocal());
                    this.completeForMq(task, variables, params.getApproveMessage(), true, params.getApproveUserId(), user);
                }
            }
        } else {
            List<Task> tasks = taskService.createTaskQuery().taskId(params.getTaskId()).list();
            if(tasks.isEmpty()){
                throw new BusinessException("流程待办已被他人处理或不存在！");
            }

            for (Task task : tasks) {
                if(!user.getId().equals(task.getAssignee())){
                    // 没签出的情况下，先看当前用户是否在审批列表里
                    List<IdentityLink> listId = taskService.getIdentityLinksForTask(task.getId());
                    List<String> uGroup = listId.stream().filter(f -> f.getType().equals("candidate")).map(IdentityLink::getGroupId).collect(Collectors.toList());
                    List<String> resUser = fSysUserService.getUserListByStationIds(String.join(",", uGroup)).stream().map(com.rf.richfitwheel.admin.sys.model.User::getId).collect(Collectors.toList());
                    if(resUser.contains(user.getId())){
                        //先签出
                        wfProcessService.doClaim(task.getId(), user.getId());
                    }else{
                        throw new BusinessException("对不起，您没有此流程操作权限，如果是未签出任务请到业务系统首页待办任务处进行签出后再处理！");
                    }
                }
                task = taskService.createTaskQuery().taskId(task.getId()).singleResult();
                task.setDescription(params.getApproveAdvice());//审批意见
                task.setFileId(params.getFileId());
                taskService.saveTask(task);
                taskService.addComment(task.getId(), task.getProcessInstanceId(), params.getApproveMessage());
                taskService.setVariablesLocal(task.getId(), params.getVariablesLocal());//本地参数
                if (task.getTaskState().equals(WorkflowContants.ProcessResult.BACK.getValue())) {
                    if (params.getSubmitToPrev().equals("y")) {//是否配置跳转到上一个退回的审批结点
                        List<WfProcessTransfer> wfProcessTransfers = wfProcessTransferService.getListByProcInstIdAndToActIdOrderByCreateDateDesc(task.getProcessInstanceId(), task.getTaskDefinitionKey());
                        if (!wfProcessTransfers.isEmpty()) {//找不着就按顺序提交
                            //退回的时候不需要知道审批人，会默认取上一次审批人
                            runtimeService.removeVariable(params.getProcessInstanceId(), "approveUserId");
                            wfProcessService.doForward(task.getId(), wfProcessTransfers.get(0).getTaskId(), params.getApproveMessage());//
                        } else {
                            this.completeForMq(task, variables, params.getApproveMessage(), false, params.getApproveUserId(), user);
                        }
                    } else {//没有配置就按顺序提交
                        this.completeForMq(task, variables, params.getApproveMessage(), false, params.getApproveUserId(), user);
                    }
                } else {//正常提交
                    this.completeForMq(task, variables, params.getApproveMessage(), false, params.getApproveUserId(), user);
                }
            }
        }
        return params;
    }

    public void completeForMq(Task task, Map<String, Object> variables, String approveMessage, boolean first, String approveUserId, UserVO user) throws Exception {
        Map<String, Object> hisVariables = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(task.getProcessInstanceId()).singleResult().getProcessVariables();
        hisVariables.putAll(variables);
        WfAuthRule wfAuthRule = wfProcessService.validAuthRules(task, hisVariables);//验证授权规则
        List<String> users = new ArrayList<>();
        users.add(task.getAssignee());
        if (ObjectUtils.isEmpty(wfAuthRule)) {//没有授权规则
            wfProcessService.recordTransfer(task, variables);
            taskService.complete(task.getId(), variables);//完成任务
        } else {
            if (wfAuthRule.getToStationId().equals("end")) {
                //授权规则跳转到结束则授权流程结束,结束之前先判断后续节点有没有授权规则，如果后续节点有不满足的授权规则的话就不能跳转到结束
                //上级设置了无条件参与的情况下也不允许结束
                if(wfProcessService.checkAllWfAuthRuleFollow(task, variables)){
                    //后面还有授权规则，不允许结束，执行下一个节点
                    wfProcessService.recordTransfer(task, variables);
                    taskService.complete(task.getId(), variables);//完成任务
                }else{
                    ActivitiEvent event = ActivitiEventBuilder.createEvent(ActivitiEventType.ENTITY_SUSPENDED, task.getExecutionId(), task.getProcessInstanceId(), task.getProcessDefinitionId());
                    runtimeService.deleteProcessInstance(task.getProcessInstanceId(), null);//流程结束
                    runtimeService.dispatchEvent(event);
                }
            } else {//找到授权规则跳转节点
                WfProcessTask wfProcessTask = wfProcessTaskService.getByStationProcessOrderId(wfAuthRule.getToStationId());
                if (ObjectUtils.isEmpty(wfProcessTask)) {//没找到授权规则跳转节点正常提交
                    wfProcessService.recordTransfer(task, variables);
                    taskService.complete(task.getId(), variables);//完成任务
                } else {//找到就跨级跳转
                    wfProcessService.doJump(task, wfProcessTask.getTaskDefKey(), approveMessage, variables);
                }
            }
        }
        /*HistoricProcessInstance his = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).includeProcessVariables().singleResult();
        String moduleType = variables.get("moduleType") == null ?
                (String) his.getProcessVariables().get("moduleType") : (String) variables.get("moduleType");
        //将当前节点置为已办发给门户
        if(!first){
            portalTodoSync.todoSyncDone(task, users, moduleType);
        }*/
        wfProcessService.dealWithNextTaskForMq(task.getProcessInstanceId(), variables, approveUserId, user);//处理下一个节点，如果下一个节点任务的审批人和岗位对应人跟前面的审批人一样，则自动提交任务
    }
    public void complete(Task task, Map<String, Object> variables, String approveMessage, boolean first, String approveUserId) throws Exception {
        Map<String, Object> hisVariables = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(task.getProcessInstanceId()).singleResult().getProcessVariables();
        hisVariables.putAll(variables);
        WfAuthRule wfAuthRule = wfProcessService.validAuthRules(task, hisVariables);//验证授权规则
        List<String> users = new ArrayList<>();
        users.add(task.getAssignee());
        if (ObjectUtils.isEmpty(wfAuthRule)) {//没有授权规则
            wfProcessService.recordTransfer(task, variables);
            taskService.complete(task.getId(), variables);//完成任务
        } else {
            if (wfAuthRule.getToStationId().equals("end")) {
                //授权规则跳转到结束则授权流程结束,结束之前先判断后续节点有没有授权规则，如果后续节点有不满足的授权规则的话就不能跳转到结束
                //上级设置了无条件参与的情况下也不允许结束
                if(wfProcessService.checkAllWfAuthRuleFollow(task, variables)){
                    //后面还有授权规则，不允许结束，执行下一个节点
                    wfProcessService.recordTransfer(task, variables);
                    taskService.complete(task.getId(), variables);//完成任务
                }else{
                    ActivitiEvent event = ActivitiEventBuilder.createEvent(ActivitiEventType.ENTITY_SUSPENDED, task.getExecutionId(), task.getProcessInstanceId(), task.getProcessDefinitionId());
                    runtimeService.deleteProcessInstance(task.getProcessInstanceId(), null);//流程结束
                    runtimeService.dispatchEvent(event);
                }
            } else {//找到授权规则跳转节点
                WfProcessTask wfProcessTask = wfProcessTaskService.getByStationProcessOrderId(wfAuthRule.getToStationId());
                if (ObjectUtils.isEmpty(wfProcessTask)) {//没找到授权规则跳转节点正常提交
                    wfProcessService.recordTransfer(task, variables);
                    taskService.complete(task.getId(), variables);//完成任务
                } else {//找到就跨级跳转
                    wfProcessService.doJump(task, wfProcessTask.getTaskDefKey(), approveMessage, variables);
                }
            }
        }
        /*HistoricProcessInstance his = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).includeProcessVariables().singleResult();
        String moduleType = variables.get("moduleType") == null ?
                (String) his.getProcessVariables().get("moduleType") : (String) variables.get("moduleType");
        //将当前节点置为已办发给门户
        if(!first){
            portalTodoSync.todoSyncDone(task, users, moduleType);
        }*/
        wfProcessService.dealWithNextTask(task.getProcessInstanceId(), variables, approveUserId);//处理下一个节点，如果下一个节点任务的审批人和岗位对应人跟前面的审批人一样，则自动提交任务
    }


    @Override
    public PageUtils getToDoList(Map<String, Object> params, UserVO user) {
        PageUtils pageUtils = PageUtils.getPageInfo(params);
        List<WfTaskVo> taskList = this.findTodoTask(user, pageUtils, params);
        pageUtils.setList(taskList);
        return pageUtils;
    }

    @Override
    public List<Map<String, Object>> getCanRecallTasks(String processInstanceId, UserVO user) {
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        Set<ActivityImpl> activities = new HashSet<>();
        for (Task task : tasks) {
            ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) this.repositoryService.getProcessDefinition(task.getProcessDefinitionId());
            ActivityImpl nowActivity = processDefinitionEntity.findActivity(task.getTaskDefinitionKey());
            Set<ActivityImpl> activitySet = this.wfProcessService.findPrevUserTaskActivitys(nowActivity);
            activities.addAll(activitySet);
        }
        List<Map<String, Object>> taskList = new LinkedList<>();
        for (ActivityImpl activity : activities) {
            List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskDefinitionKey(activity.getId()).taskAssignee(user.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
            if (!historicTaskInstances.isEmpty()) {
                HistoricTaskInstance historicTaskInstance = historicTaskInstances.get(0);
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("taskId", historicTaskInstance.getId());
                map.put("taskDefKey", historicTaskInstance.getTaskDefinitionKey());
                map.put("taskName", historicTaskInstance.getName());
                Map<String, Object> userMap = (Map<String, Object>) this.fSysUserService.info(historicTaskInstance.getAssignee()).get("user");
                map.put("approveUserName", userMap.get("username").toString());
                map.put("approveDate", historicTaskInstance.getStartTime());
                List<Comment> comments = taskService.getTaskComments(historicTaskInstance.getId());
                if (!comments.isEmpty()) {
                    map.put("approveMessage", comments.get(0).getFullMessage());
                }
                taskList.add(map);
            }
        }
        return taskList;
    }


    @Override
    public List<Task> getTaskByProcessInstanceIdAndUserId(String processInstanceId, String userId) {
        return this.taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(userId).list();
    }

    @Override
    public WfTaskVo getWfTaskVoByBusinesskey(String businessKey, UserVO user) {
        ProcessInstance processInstance = this.wfProcessService.getProcessInstanceByBusinessKey(businessKey);
        if (ObjectUtils.isEmpty(processInstance)) {
            //如果有挂起的流程则continue
            return null;
        }
        List<Task> tasks = this.getTaskByProcessInstanceIdAndUserId(processInstance.getId(), user.getId());
        if (tasks.isEmpty()) {
            return null;
        }
        return assembleTaskVo(tasks.get(0));
    }

    @Override
    public List<WfTaskVo> findTodoTask(UserVO user, PageUtils pageUtils, Map<String, Object> params) {

        TaskQuery taskQuery = this.taskService.createTaskQuery().taskCandidateOrAssigned(user.getId());
        if(params.containsKey("folderCode")){
//            taskQuery.processDefinitionKeyLike("%" + params.get("folderCode").toString() + "%");
            taskQuery.processVariableValueLike("approveNo", params.get("folderCode").toString() + "%");
        }
        if(params.containsKey("moduleType")){
            List<String> modList = new ArrayList<>(Arrays.asList(params.get("moduleType").toString().split(",")));
            if(modList.contains("capitalbudget")){
                modList.add("capitalBudget");
            }
            if(modList.size() > 1){
                taskQuery.or();
                for(String m : modList){
                    taskQuery.processVariableValueEquals("moduleType", m);
                }
                taskQuery.endOr();
            }else if(modList.size() == 1){
                taskQuery.processVariableValueEquals("moduleType", modList.get(0));
            }else{
                //
            }
        }
        
        int totalCount = taskQuery.list().size();
        List<Task> tasks = taskQuery.includeProcessVariables().orderByTaskCreateTime().desc().listPage((pageUtils.getPage() - 1) * pageUtils.getLimit(), pageUtils.getLimit());
        pageUtils.setTotalCount(totalCount);
        return getWfTaskVoList(tasks);
    }

    @Override
    public String getFileIdByTaskId(String taskId) {
        Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
        return task.getFileId();
    }

    @Override
    public boolean checkByBusinessKey(String businessKey, UserVO user) {
        WfTaskVo wfTaskVo = this.getWfTaskVoByBusinesskey(businessKey, user);
        String processInstanceId = Optional.ofNullable(wfTaskVo).map(WfTaskVo :: getProcessInstanceId).orElse("");
        return StringUtils.isNotBlank(processInstanceId) ? Boolean.TRUE : Boolean.FALSE;
    }
    
    /**
     * 委托办理
     *
     * @param taskId 任务id
     * @param userId 被委托人
     */
    @Override
    public void delegateTask(String taskId, String userId){
        taskService.delegateTask(taskId, userId);
    }
    
    /**
     * 根据任务id获取任务信息
     *
     * @param taskId 任务id
     * @return 任务信息
     */
    @Override
    public WfTaskVo getTaskInfoById(String taskId){
        Task task = this.taskService.createTaskQuery().taskId(taskId).includeProcessVariables().singleResult();
        if(task == null){
            WfTaskVo taskNull = new WfTaskVo();
            HistoricTaskInstance ins = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            taskNull.setProcessInstanceId(ins.getProcessInstanceId());
            return taskNull;
        }
        WfTaskVo taskVo = assembleTaskVo(task);
        ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        taskVo.setBusinessKey(ins.getBusinessKey());
        return taskVo;
    }
    
    /**
     * 根据流程实例id获取任务信息
     *
     * @param processInstanceId 流程实例id
     * @return 流程实例信息
     */
    @Override
    public Map<String, Object> getProcessInstanceById(String processInstanceId){
        HistoricProcessInstance his = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).includeProcessVariables().singleResult();
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(his.getProcessDefinitionId());
        Map<String, Object> map = new HashMap<>();
        map.put("approveNo", his.getProcessVariables().get("approveNo"));
        map.put("businessKey", his.getBusinessKey());
        map.put("creatorName", identityService.getUserInfo(his.getStartUserId(), "LAST_"));
        map.put("description", his.getName());
        map.put("detailPage", processDefinition.getCategory());
        map.put("processDefinitionId", his.getProcessDefinitionId());
        map.put("processInstanceId", processInstanceId);
        map.put("processName", processDefinition.getName());
        map.put("startTime", DateUtils.format(his.getStartTime(), DateUtils.DATE_TIME_PATTERN));
        map.put("startUserId", his.getStartUserId());
        if (his.getEndTime() != null) {
            if (his.getDeleteReason() == null) {
                map.put("state", "2");
            } else {
                map.put("state", "3");
            }
            map.put("endTime", DateUtils.format(his.getEndTime(), DateUtils.DATE_TIME_PATTERN));
        } else {
            map.put("state", "1");
        }
        return map;
    }
    
    /**
     * 根据任务id查询节点是否需要ukey
     *
     * @param taskId 任务id
     * @return needKey
     */
    @Override
    public Map<String, String> getTaskNeedKey(String taskId){
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        WfProcessTaskExample example = new WfProcessTaskExample();
        WfProcessTaskExample.Criteria criteria = example.createCriteria();
        criteria.andProcDefIdEqualTo(task.getProcessDefinitionId());
        criteria.andTaskDefKeyEqualTo(task.getTaskDefinitionKey());
        List<WfProcessTask> wfProcessTasks = wfProcessTaskMapper.selectByExample(example);
        Map<String, String> map = new HashMap<>();
        if(!wfProcessTasks.isEmpty()){
            WfStationProcessOrder  wfStationProcessOrder = wfStationProcessOrderMapper.selectByPrimaryKey(wfProcessTasks.get(0).getStationProcessOrderId());
            if(wfStationProcessOrder != null){
                WfStationProcess wfStationProcess = wfStationProcessMapper.selectByPrimaryKey(wfStationProcessOrder.getStationProcessId());
                String orgCode = wfStationProcess.getOrgCode();
                OrgVO orgVO = sysOrgFeignService.getOrgVOObjectByOrgCode(orgCode);
                map.put("needKey", wfStationProcessOrder.getNeedKey() == null ? "0" : wfStationProcessOrder.getNeedKey());
                map.put("orgId", orgVO.getId());
//                return wfStationProcessOrder.getNeedKey() == null ? "0" : wfStationProcessOrder.getNeedKey();
            }
        }
        return map;
    }
    
    /**
     * 查询第一个节点是否需要ukey
     *
     * @param folderCode 流程目录编码
     * @param orgCode    机构编码
     * @return needKey
     */
    @Override
    public String getTaskNeedKeyFirst(String folderCode, String orgCode){
        WfStationProcessExample example = new WfStationProcessExample();
        WfStationProcessExample.Criteria criteria = example.createCriteria();
        criteria.andFolderCodeEqualTo(folderCode);
        criteria.andOrgCodeEqualTo(orgCode);
        List<WfStationProcess> processesList = wfStationProcessMapper.selectByExample(example);
        if(!processesList.isEmpty()){
            WfStationProcessOrderExample example1 = new WfStationProcessOrderExample();
            WfStationProcessOrderExample.Criteria criteria1 = example1.createCriteria();
            criteria1.andStationProcessIdEqualTo(processesList.get(0).getId());
            criteria1.andApproveOrderEqualTo(1);
            List<WfStationProcessOrder> orders = wfStationProcessOrderMapper.selectByExample(example1);
            if(!orders.isEmpty()){
                return orders.get(0).getNeedKey() == null ? "0" : orders.get(0).getNeedKey();
            }
        }
        return "0";
    }
    
    /**
     * 获取首节点信息
     *
     * @param processDefinitionId 流程定义id
     * @return 流程首节点信息
     */
    @Override
    public UserTask getFirstUserTaskDef(String processDefinitionId){
        BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(processDefinitionId);
        // 获取所有节点
        Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
        ActivityImpl activityImpl = null;
        for (FlowElement e : flowElements) {
            if (e instanceof StartEvent) {
                StartEvent startEvent = (StartEvent) e;
                ActivityImpl startEventActivityImpl = processDefinitionEntity.findActivity(startEvent.getId());// 当前节点
                List<PvmTransition> outTransitions = startEventActivityImpl.getOutgoingTransitions();
                for (PvmTransition tr : outTransitions) {
                    PvmActivity ac = tr.getDestination(); // 获取线路的终点节点
                    if ("userTask".equals(ac.getProperty("type"))) {
                        activityImpl = processDefinitionEntity.findActivity(ac.getId());// 当前节点
                        break;
                    } else if ("manualTask".equals(ac.getProperty("type"))) {
                        List<PvmTransition> outTransitionsManual = startEventActivityImpl.getOutgoingTransitions();
                        for (PvmTransition trManual : outTransitionsManual) {
                            PvmActivity acManual = trManual.getDestination(); // 获取线路的终点节点
                            if ("userTask".equals(acManual.getProperty("type"))) {
                                activityImpl = processDefinitionEntity.findActivity(ac.getId());// 当前节点
                                break;
                            }
                        }
                    }
                }
                break;
            }
        }
        if(activityImpl != null){
            String actId = activityImpl.getId();
            List<FlowElement> ll = flowElements.stream().filter(m -> actId.equals(m.getId())).collect(Collectors.toList());
            if(!ll.isEmpty()){
                return (UserTask) ll.get(0);
            }
        }
        return null;
    }

    /**
     * 批量查询节点是否需要ukey
     *
     * @param taskIdArr 任务id
     * @return map
     */
    @Override
    public Map<String, Map<String, String>> getTaskNeedKeyBatch(String[] taskIdArr) {
        Map<String, Object> param = new HashMap<>();
        param.put("taskIdArr", Arrays.asList(taskIdArr));
        List<Map<String, Object>> task = wfCommonMapper.selectNeedKeyBatch(param);
        Map<String, Map<String, String>> needP = new HashMap<>();
        for (Map<String, Object> stringObjectMap : task) {
            Map<String, String> needC = new HashMap<>();
            needC.put("needKey", stringObjectMap.get("need_key").toString());
            needC.put("orgId", stringObjectMap.get("orgId").toString());
            needP.put(stringObjectMap.get("taskId").toString(), needC);
        }
        return needP;
    }

    /**
     * 将Task集合转为BaseVO集合
     *
     * @param tasks task集合
     * @return 转化结果
     */
    protected List<WfTaskVo> getWfTaskVoList(List<Task> tasks) {
        List<WfTaskVo> taskList = new ArrayList<>();
        for (Task task : tasks) {
            //获取当前流程下的key为businessType的variable
            HistoricProcessInstance hProcessInstance = historyService.createHistoricProcessInstanceQuery().unfinished().
                    processInstanceId(task.getProcessInstanceId()).singleResult();
            WfTaskVo wfTaskVo = assembleTaskVo(task);
            wfTaskVo.setDescription(hProcessInstance.getName());
            taskList.add(wfTaskVo);
        }
        return taskList;
    }

    public WfTaskVo assembleTaskVo(Task task) {
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
        //获取当前流程下的key为businessType的variable
        WfTaskVo wfTaskVo = new WfTaskVo();

        Map<String, Object> variables = task.getProcessVariables();
        String businessKey = (String) variables.get("businessKey");
        String processKey = (String) variables.get("processKey");
        String approveNo = (String) variables.get("approveNo");
        String orgCode = (String) variables.get("orgCode");
        String processCode = (String) variables.get("processCode");
        String moduleType = (String) variables.get("moduleType");
        String queueName = (String) variables.get("queueName");
        String submitToPrev = "n";
        if (variables.containsKey("submitByOrder")) {
            submitToPrev = (String) variables.get("submitToPrev");
        }
        wfTaskVo.setBusinessKey(businessKey);
        wfTaskVo.setProcessKey(processKey);
        wfTaskVo.setApproveNo(approveNo);
        wfTaskVo.setOrgCode(orgCode);
        wfTaskVo.setProcessCode(processCode);
        wfTaskVo.setModuleType(moduleType);
        wfTaskVo.setQueueName(queueName);
        wfTaskVo.setSubmitToPrev(submitToPrev);
        wfTaskVo.setVariables(variables);
        wfTaskVo.setTask(task);
        wfTaskVo.setTaskId(wfTaskVo.getTask().getId());
        wfTaskVo.setTaskKey(wfTaskVo.getTask().getTaskDefinitionKey());
        wfTaskVo.setTaskName(wfTaskVo.getTask().getName());
        wfTaskVo.setTaskUrl(task.getFormKey());
        wfTaskVo.setStartTime(wfTaskVo.getTask().getCreateTime());
        String startUserId = (String) variables.get("startUserId");
        String startUserName = (String) variables.get("startUserName");
        wfTaskVo.setStartUserId(startUserId);
        wfTaskVo.setStartUserName(startUserName);
        String assign = wfTaskVo.getTask().getAssignee();
        if (assign != null) {
            User user = this.identityService.createUserQuery().userId(assign).singleResult();
            assign = user.getLastName();
        }
        wfTaskVo.setAssign(assign);
        if (processDefinition != null) {
            wfTaskVo.setDetailPage(processDefinition.getCategory());
            wfTaskVo.setProcessName(processDefinition.getName());
            wfTaskVo.setProcessDefinitionKey(processDefinition.getKey());
        }
        wfTaskVo.setProcessInstanceId(task.getProcessInstanceId());
        wfTaskVo.setProcessDefinitionId(task.getProcessDefinitionId());
        wfTaskVo.setTaskState(task.getTaskState());
        return wfTaskVo;
    }

}
